namespace GYLite
{
    export class ExtList extends GYListV implements IKeyBoardObject{
        protected _dragData:any;
        protected _dropData:any;
        protected _dropItem:GYLite.IItemRender;
        protected _dragHandle:GYLite.GYSprite;
        protected _dataCanDrag:boolean;
        public constructor(size: number, getGridFunc?: Function, getThisObject?: any, setGridFunc?: Function, setThisObject?: any) {
            super(size, getGridFunc, getThisObject, setGridFunc, setThisObject);
            let s= this;
            s.addEventListener(egret.Event.ADDED_TO_STAGE, s.addToStage, s);
            s.addEventListener(egret.Event.REMOVED_FROM_STAGE, s.removeFromStage, s);
        }
        private addToStage(e:egret.Event):void
        {
            let s = this;
            GYLite.GYKeyboard.getInstance().addKeyListener(s);
        }
        private removeFromStage(e:egret.Event):void
        {
            let s = this;
            GYLite.GYKeyboard.getInstance().removeKeyListener(s);
        }
        public get dataCanDrag():boolean
        {
            return this._dataCanDrag;
        }
        public set dataCanDrag(val:boolean)
        {
            this._dataCanDrag = val;
        }
        protected createDragShape(touchId:number,item:GYLite.GYSprite):GYLite.GYSprite
        {
            let sp:GYLite.GYImage;
            let g:egret.Graphics;
            let s = this;
            if(s._dragHandle == null)
            {
                s._dragHandle = new GYLite.GYImage;			
                sp = <any>s._dragHandle;
                sp.mouseThrough = true;
                sp.x = s.x + item.x;
                sp.y = s.y + item.y;
                let renderTexture:egret.RenderTexture;
                renderTexture = new egret.RenderTexture;
                renderTexture.drawToTexture(item);
                // g = sp.graphics;
                // g.clear();		
                // g.beginFill(0xffffff, 0.7);
                // g.drawRect(offsetX,offsetY,w,h);
                // g.endFill();
                sp.source = renderTexture;
                sp.alpha = 0.5;
                (<any>s.parent).addElement(sp);
                let drag:GYLite.DraggerHandle;
                drag = GYLite.DraggerHandle.getInstance(sp);
                drag.addBind(function(d:GYLite.DraggerHandle):void{
                    let s =this;
                    s._dragHandle.x = (<any>s._dragHandle.parent).mouseX - d.dragMouseX;
                    s._dragHandle.y = (<any>s._dragHandle.parent).mouseY - d.dragMouseY;
                }, s);
                drag.startDrag(sp, touchId);
            }					
            return sp;
        }
        protected removeDragShape():void
        {
            let s = this;
            if(s._dragHandle)
            {
                GYLite.DraggerHandle.getInstance(s._dragHandle).clear();			
                (<egret.RenderTexture>(<GYLite.GYImage>s._dragHandle).source).dispose();
                (<GYLite.GYImage>s._dragHandle).source = null;
                s._dragHandle.dispose();
                s._dragHandle = null;
            }
        }
        protected getGrid():GYLite.IItemRender
        {var s = this;
            var item:GYLite.IItemRender;
            item = super.getGrid();		
            item.addEventListener(egret.TouchEvent.TOUCH_BEGIN, s.itemTouchBegin, s);
            item.addEventListener(egret.TouchEvent.TOUCH_END, s.itemTouchUp, s);	
            return item;
        }
        private itemTouchBegin(e:egret.TouchEvent):void
        {
            let s = this;
            if(s.dragSelect || s._canDrag)return;
            if(!s._dataCanDrag)return;		
            let item:GYLite.IItemRender = e.currentTarget;		
            s._dragData = e.currentTarget.getData();
            GYLite.GYSprite.addStageDown(item, s.itemtouchOutside, s);		
            s.addEventListener(GYLite.GYTouchEvent.TOUCH_MOVE, s.touchListMove, s);
            s.addEventListener(GYLite.MouseEvent.ROLL_OUT, s.rollOut, s);				
            let obj:ListDragData;
            let toX:number,toY:number;
            toX = item.mouseX;
            toY = item.mouseY;		
            obj = new ListDragData(s._dragData, null,toX,toY);
            if(s.hasEventListener(ListEvent.DRAG_START))					
                s.dispatchEventWith(ListEvent.DRAG_START, false, obj);
            if((<any>item).hasEventListener(ListEvent.DRAG_START))
                (<any>item).dispatchEventWith(ListEvent.DRAG_START, false, obj);		
        }
        private rollOut(e:egret.TouchEvent):void
        {
            let s = this;
            if(!s._dataCanDrag)return;
            s._dropData = null;
            if(s._dropItem)		
            {
                (<any>s._dropItem).dispatchEventWith(ListEvent.DRAG_OUT, false);
                s._dropItem = null;
            }
        }
        private itemtouchOutside(e:GYLite.GYTouchEvent):void
        {
            let s = this;
            if(!s._dataCanDrag)return;
            let tar:any;
            let toX:number,toY:number;
            let pr:any;
            let obj:ListDragData,obj2:ListDragData;
            pr = e.outsideTarget;
            while(pr && pr != GYLite.GYSprite.stage)
            {
                if(pr.receiveData && pr.receiveData.constructor == Function)
                {
                    toX = pr.mouseX;
                    toY = pr.mouseY;								
                    obj2 = new ListDragData(s._dragData, null,toX,toY);
                    if(tar == null)
                    {
                        tar = pr;
                        obj = obj2;
                    }
                    pr.receiveData(obj2);				
                }
                pr = pr.parent;
            }		
            if(obj == null)
                obj = new ListDragData(s._dragData, null,toX,toY);
            if(s._dropItem)		
            {
                (<any>s._dropItem).dispatchEventWith(ListEvent.DRAG_OUT, false, obj);
                s._dropItem = null;
            }
            s._dragData = s._dropData = null;
            s.removeEventListener(GYLite.GYTouchEvent.TOUCH_MOVE, s.touchListMove, s);
            s.removeEventListener(GYLite.MouseEvent.ROLL_OUT, s.rollOut, s);
            s.removeDragShape();
        }
        private itemTouchUp(e:egret.TouchEvent):void
        {
            let s = this;
            if(!s._dataCanDrag)return;
            if(s.dragSelect || s._canDrag)return;
            let item:GYLite.IItemRender;
            let obj:ListDragData;
            let toX:number,toY:number;
            if(s._dragHandle)
            {
                item = e.currentTarget;		
                s._dropData = item.getData();		
                toX = item.mouseX;
                toY = item.mouseY;
                obj = new ListDragData(s._dragData, s._dropData,toX,toY);
                (<any>item).dispatchEventWith(ListEvent.DRAG_OUT, false, obj);		
                if(s.hasEventListener(ListEvent.DROP))					
                    s.dispatchEventWith(ListEvent.DROP, false, obj);
                if((<any>item).hasEventListener(ListEvent.DROP))
                    (<any>item).dispatchEventWith(ListEvent.DROP, false, obj);
            }			
            
            s._dropItem = null;
            s.removeEventListener(GYLite.GYTouchEvent.TOUCH_MOVE, s.touchListMove, s);
            s.removeEventListener(GYLite.MouseEvent.ROLL_OUT, s.rollOut, s);
            s._dragData = s._dropData = null;
            s.removeDragShape();
        }
        private touchListMove(e:GYLite.GYTouchEvent):void
        {
            let s = this;
            if(!s._dataCanDrag)return;
            let item:GYLite.IItemRender;
            let pr:GYLite.GYSprite;
            let dropData:any;
            pr = e.target;
            while(pr && !GYLite.CommonUtil.GYIs(pr, GYLite.ItemRender))
            {			
                pr = <any>pr.parent;
            }
            if(pr == null)return;
            item = <any>pr;		
            s._dropData = item.getData();
            let obj:ListDragData;
            let toX:number,toY:number;
            toX = item.mouseX;
            toY = item.mouseY;
            obj = new ListDragData(s._dragData, s._dropData,toX,toY);
            if(s._dropItem && s._dropItem != item)		
                (<any>s._dropItem).dispatchEventWith(ListEvent.DRAG_OUT, false, obj);					
            s._dropItem = item;
            if(s.hasEventListener(ListEvent.DRAG_ENTER))					
                s.dispatchEventWith(ListEvent.DRAG_ENTER, false, obj);
            if((<any>item).hasEventListener(ListEvent.DRAG_ENTER))
                (<any>item).dispatchEventWith(ListEvent.DRAG_ENTER, false, obj);
            s.createDragShape(e.touchPointID, <any>item);
        }	
        ///键盘操控
        public keyFocus(): boolean
        {
            return true;
        }
        public kDown(keyCode: number): void
        {let s =this;			
            let isCtrlDown:boolean,isAltDown:boolean;
            isCtrlDown = GYLite.GYKeyboard.getInstance().isCtrlDown();
            isAltDown = GYLite.GYKeyboard.getInstance().isAltDown();
            if(isCtrlDown)
            {
                if(keyCode == GYLite.Keyboard.A)
                {
                    s.selectedData = s._dataProvider[s._dataProvider.length - 1];
                    s.selectLine(s._dataProvider[0],s.selectedData,true);
                }
            }		
        }
        public kUp(keyCode: number): void
        {
    
        }
    }
    export class ListEvent{
        /**列表项拖拽开始*/public static DRAG_START:string = "list_drag_start";
        /**列表项拖拽到外部，如果拖拽到非列表项上，会调用非列表项的receiveData方法以便传递数据*/public static DRAG_OUT:string = "list_drag_out";
        /**列表项拖拽进入其他列表项*/public static DRAG_ENTER:string = "list_drag_enter";
        /**列表项放置到其他列表项上*/public static DROP:string = "list_drop";
    }
    export class ListDragData{
        /**拖拽的数据，列表项的数据**/public dragData:any;
        /**放置目标的数据，通常是另外一个列表项的数据**/public dropData:any;
        /**相对放置目标的放置坐标Y**/public offsetX:number;
        /**相对放置目标的放置坐标Y**/public offsetY:number;
        constructor(dragData:any, dropData:any=null, offsetX:number=0,offsetY:number=0){
            let s = this;
            s.dragData = dragData;
            s.dropData = dropData;
            s.offsetX = offsetX;
            s.offsetY = offsetY;
        }
    }
}
